#ifndef _COMMON_LOGGER_H_
#define _COMMON_LOGGER_H_

#include <map>
using std::map;
#include <string>
using std::string;

#include "mutex.h"
#include "singleton.h"

#define LOG_DIR     "/../log/"

enum LogLevel
{
    LOGLEVEL_NOLOG = 0,
    LOGLEVEL_NOTICE,
    LOGLEVEL_ERROR,
    LOGLEVEL_INFO,
    LOGLEVEL_DEBUG,
    LOGLEVEL_COUNT
};

#define LOG_PRINTF(pLog,level, ...)    if(NULL != pLog) (*pLog).Logout(level, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)

#define LOG_NOTICE(pLog, ...)    if(NULL != pLog) (*pLog).Logout(LOGLEVEL_NOTICE, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define LOG_ERROR(pLog, ...)     if(NULL != pLog) (*pLog).Logout(LOGLEVEL_ERROR, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define LOG_INFO(pLog, ...)      if(NULL != pLog) (*pLog).Logout(LOGLEVEL_INFO, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define LOG_DEBUG(pLog, ...)     if(NULL != pLog) (*pLog).Logout(LOGLEVEL_DEBUG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)

class CLog
{
    friend class CLogger;

    CLog(const char* filename);

public:

    ~CLog();

    void Logout(int level, const char* file, int line, const char* func, char* msg, ...);

private:

    FILE*   m_file;
    string  m_name;
    string  m_time;
    int     m_index;
    CMutex  m_lock;
};

class CLogger
{
    friend class CSingleton<CLogger>;

    typedef map<string, CLog*> LOG_MAP;

    CLogger();

public:

    ~CLogger();

    CLog* GetSysLog();
    
    CLog* GetLog(const char* name);

private:

    CLog* m_syslog;

    CMutex  m_lock;

    LOG_MAP m_logmap;
};

#define sLogger        CSingleton<CLogger>::Instance()
#define GET_SYS_LOG()  sLogger.GetSysLog()
#define GET_LOG(name)  sLogger.GetLog(name)

#endif //_COMMON_LOGGER_H_
